package com.parking.order.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.parking.common.core.model.RedisKey;
import com.parking.common.core.util.DateUtil;
import com.parking.common.web.util.RedisUtil;
import com.parking.order.dao.CentifiedIncomeDao;
import com.parking.order.dao.PlatformIncomeDao;
import com.parking.order.dao.RentersIncomeDao;
import com.parking.order.model.CentifiedIncome;
import com.parking.order.model.PlatformIncome;
import com.parking.order.model.RentersIncome;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Set;

/**
 * 收入统计定时任务类
 * */
@Component
public class IncomeTask {
    /**
     * 平台收入数据层
     * */
    @Autowired
    private PlatformIncomeDao platformIncomeDao;
    /**
     * 出租客收入数据层
     * */
    @Autowired
    private RentersIncomeDao rentersIncomeDao;
    /**
     * 物业收入数据层
     * */
    @Autowired
    private CentifiedIncomeDao centifiedIncomeDao;
    /**
     * Redis工具类
     * */
    @Autowired
    private RedisUtil redisUtil;


    /**
     * 平台收入统计定时任务
     * 定时时间 每天整小时
     * 23-24点的收入算第二天
     * */
    @Transactional
    @XxlJob("checkPlatformDailyIncome")
    public void checkPlatformDailyIncome(){
        LocalDate now = LocalDate.now();

        if(redisUtil.exist(RedisKey.platformIncome())&&redisUtil.exist(RedisKey.platformStallHour())){
            BigDecimal platIncome = new BigDecimal(redisUtil.get(RedisKey.platformIncome()));
            redisUtil.set(RedisKey.platformIncome(),new BigDecimal(redisUtil.get(RedisKey.platformIncome())).add(platIncome.negate()).toString());

            Integer enduHour = Integer.valueOf(redisUtil.get(RedisKey.platformStallHour()));
            redisUtil.set(RedisKey.platformStallHour(), String.valueOf((Integer.parseInt(redisUtil.get(RedisKey.platformStallHour()))-enduHour)));

            checkPlatformDailyIncome(now,enduHour,platIncome);
            checkPlatformMonthlyIncome(now,enduHour,platIncome);

        }
    }

    /**
     * 出租客收入统计定时任务
     * 定时时间 每天整小时
     * 23-24点的收入算第二天
     * */
    @Transactional
    @XxlJob("checkRentersDailyIncome")
    public void checkRentersDailyIncome(){
        LocalDate now = LocalDate.now();

        Set<String> renterIdsByIncome = redisUtil.ZSetRank(RedisKey.rentersIncome(), 0, -1);
        Set<String> renterIdsByHour = redisUtil.ZSetRank(RedisKey.rentersStallHour(),0,-1);

        for (String renterId : renterIdsByIncome) {
            if(renterIdsByHour.contains(renterId)){
                BigDecimal platIncome = BigDecimal.valueOf(redisUtil.ZSetScore(RedisKey.rentersIncome(), renterId));
                redisUtil.zadd(RedisKey.rentersIncome(),renterId, BigDecimal.valueOf(redisUtil.ZSetScore(RedisKey.platformIncome(), renterId)).add(platIncome.negate()).doubleValue());

                Integer enduHour = (int) redisUtil.ZSetScore(RedisKey.rentersStallHour(), renterId);
                redisUtil.setZSet(RedisKey.rentersStallHour(),renterId,-enduHour);

                checkRentersDailyIncome(now,Integer.valueOf(renterId),enduHour,platIncome);
                checkRentersMonthlyIncome(now,Integer.valueOf(renterId),enduHour,platIncome);

            }
        }
    }

    /**
     * 物业收入统计定时任务
     * 定时时间 每天整小时
     * 23-24点的收入算第二天
     * */
    @Transactional
    @XxlJob("checkCertifiedDailyIncome")
    public void checkCertifiedDailyIncome(){
        LocalDate now = LocalDate.now();

        Set<String> certifiedIdsByIncome = redisUtil.ZSetRank(RedisKey.certifiedIncome(), 0, -1);
        Set<String> certifiedIdsByHour = redisUtil.ZSetRank(RedisKey.certifiedStallHour(),0,-1);

        for (String certifiedId : certifiedIdsByIncome) {
            if(certifiedIdsByHour.contains(certifiedId)){
                BigDecimal platIncome = BigDecimal.valueOf(redisUtil.ZSetScore(RedisKey.certifiedIncome(), certifiedId));
                redisUtil.zadd(RedisKey.certifiedIncome(),certifiedId, BigDecimal.valueOf(redisUtil.ZSetScore(RedisKey.certifiedIncome(), certifiedId)).add(platIncome.negate()).doubleValue());

                Integer enduHour = (int) redisUtil.ZSetScore(RedisKey.certifiedStallHour(), certifiedId);
                redisUtil.setZSet(RedisKey.certifiedStallHour(),certifiedId,-enduHour);

                checkCentifiedDailyIncome(now,Integer.valueOf(certifiedId),enduHour,platIncome);
                checkCentifiedMonthlyIncome(now,Integer.valueOf(certifiedId),enduHour,platIncome);

            }
        }
    }

    /**
     * 根据参数添加或修改每日平台收入数据
     * 参数   time        时间
     *       enduHour    出租小时数
     *       income  收入
     * */
    public void checkPlatformDailyIncome(LocalDate time, Integer enduHour, BigDecimal income){
        String dailyStr = DateUtil.localDateToString(time);
        PlatformIncome platIncome = platformIncomeDao.selectOne(new QueryWrapper<PlatformIncome>().eq("yearMonthTime",dailyStr));
        if(enduHour!=0||!income.equals(new BigDecimal("0"))){
            if(platIncome==null){
                platformIncomeDao.insert(new PlatformIncome(dailyStr,income,enduHour));
            }else {
                platIncome.setIncome(platIncome.getIncome().add(income));
                platIncome.setYearMonthHour(platIncome.getYearMonthHour()+enduHour);
                platformIncomeDao.updateById(platIncome);
            }
        }
    }

    /**
     * 根据参数添加或修改每月平台收入数据
     * 参数   time        时间
     *       enduHour    出租小时数
     *       income  收入
     * */
    public void checkPlatformMonthlyIncome(LocalDate time, Integer enduHour, BigDecimal income){
        String monthlyStr = DateUtil.localDateToString(time,"yyyy-MM");
        PlatformIncome platIncome = platformIncomeDao.selectOne(new QueryWrapper<PlatformIncome>().eq("yearMonthTime",monthlyStr));
        if(enduHour!=0||!income.equals(new BigDecimal("0"))){
            if(platIncome==null){
                platformIncomeDao.insert(new PlatformIncome(monthlyStr,income,enduHour));
            }else {
                platIncome.setIncome(platIncome.getIncome().add(income));
                platIncome.setYearMonthHour(platIncome.getYearMonthHour()+enduHour);
                platformIncomeDao.updateById(platIncome);
            }
        }
    }

    /**
     * 根据参数添加或修改每日出租客收入数据
     * 参数   rentersInfoId 出租客Id
     *       time        时间
     *       enduHour    出租小时数
     *       platIncome  收入
     * */
    public void checkRentersDailyIncome(LocalDate time, Integer rentersInfoId, Integer enduHour, BigDecimal income){
        String dailyStr = DateUtil.localDateToString(time);
        RentersIncome rentersIncome = rentersIncomeDao.selectOne(new QueryWrapper<RentersIncome>().eq("yearMonthTime",dailyStr));
        if(enduHour!=0||!income.equals(new BigDecimal("0"))){
            if(rentersIncome==null){
                rentersIncomeDao.insert(new RentersIncome(rentersInfoId,income,dailyStr,enduHour));
            }else {
                rentersIncome.setIncome(rentersIncome.getIncome().add(income));
                rentersIncome.setYearMonthHour(rentersIncome.getYearMonthHour()+enduHour);
                rentersIncomeDao.updateById(rentersIncome);
            }
        }
    }

    /**
     * 根据参数添加或修改每月出租客收入数据
     * 参数   rentersInfoId 出租客Id
     *       time          时间
     *       enduHour      出租小时数
     *       platIncome    收入
     * */
    public void checkRentersMonthlyIncome(LocalDate time, Integer rentersInfoId,Integer enduHour, BigDecimal income){
        String monthlyStr = DateUtil.localDateToString(time,"yyyy-MM");
        RentersIncome rentersIncome = rentersIncomeDao.selectOne(new QueryWrapper<RentersIncome>().eq("yearMonthTime",monthlyStr));
        if(enduHour!=0||!income.equals(new BigDecimal("0"))){
            if(rentersIncome==null){
                rentersIncomeDao.insert(new RentersIncome(rentersInfoId,income,monthlyStr,enduHour));
            }else{
                rentersIncome.setIncome(rentersIncome.getIncome().add(income));
                rentersIncome.setYearMonthHour(rentersIncome.getYearMonthHour()+enduHour);
                rentersIncomeDao.updateById(rentersIncome);
            }
        }
    }

    /**
     * 根据参数添加或修改每日物业收入数据
     * 参数   certifiedInfoId 物业Id
     *       time        时间
     *       enduHour    出租小时数
     *       platIncome  收入
     * */
    public void checkCentifiedDailyIncome(LocalDate time, Integer certifiedInfoId, Integer enduHour, BigDecimal income){
        String dailyStr = DateUtil.localDateToString(time);
        CentifiedIncome certifiedIncome = centifiedIncomeDao.selectOne(new QueryWrapper<CentifiedIncome>().eq("yearMonthTime",dailyStr));
        if(enduHour!=0||!income.equals(new BigDecimal("0"))){
            if(certifiedIncome==null){
                centifiedIncomeDao.insert(new CentifiedIncome(certifiedInfoId,dailyStr,income,enduHour));
            }else {
                certifiedIncome.setIncome(certifiedIncome.getIncome().add(income));
                certifiedIncome.setYearMonthHour(certifiedIncome.getYearMonthHour()+enduHour);
                centifiedIncomeDao.updateById(certifiedIncome);
            }
        }
    }

    /**
     * 根据参数添加或修改每月物业收入数据
     * 参数   certifiedInfoId 物业Id
     *       time            时间
     *       enduHour        出租小时数
     *       platIncome      收入
     * */
    public void checkCentifiedMonthlyIncome(LocalDate time, Integer certifiedInfoId,Integer enduHour, BigDecimal income){
        String monthlyStr = DateUtil.localDateToString(time,"yyyy-MM");
        CentifiedIncome certifiedIncome = centifiedIncomeDao.selectOne(new QueryWrapper<CentifiedIncome>().eq("yearMonthTime",monthlyStr));
        if(enduHour!=0||!income.equals(new BigDecimal("0"))){
            if(certifiedIncome==null){
                centifiedIncomeDao.insert(new CentifiedIncome(certifiedInfoId,monthlyStr,income,enduHour));
            }else{
                certifiedIncome.setIncome(certifiedIncome.getIncome().add(income));
                certifiedIncome.setYearMonthHour(certifiedIncome.getYearMonthHour()+enduHour);
                centifiedIncomeDao.updateById(certifiedIncome);
            }
        }
    }
}
